Widget: Don’t call reset() on NULL EventController
authorDaniel Boles <dboles@src.gnome.org>
Thu, 18 Jan 2018 00:51:24 +0000 (00:51 +0000)
committerDaniel Boles <dboles@src.gnome.org>
Mon, 22 Jan 2018 19:09:50 +0000 (19:09 +0000)
commitb8e2430486ae3dac4f0c0441608f2d1b032ac794
tree6d7cd28c1d8d7d9b250b22b60f5e1e4c99e374ae
parent814c55d473c6a7ab9f930421aad5612a351ba68d
Widget: Don’t call reset() on NULL EventController

GtkGesture is a GtkEventController. gtk_event_controller_dispose() calls
_gtk_widget_remove_controller(). That NULLs the pointer-to-Controller in
our EventControllerData but does not delete said ECData from our GList.

Subsequently, if that same Widget gets unparent()ed, that method calls
unset_state_flags(), which leads to doing reset_controllers() if we are
insensitive. Now, unlike most most other loops over the GList of ECData,
reset_controllers() does not skip nodes whose pointer-to-Controller is
NULL. So, we call gtk_event_controller_reset(NULL) and get a CRITICAL.

This surfaced in a gtkmm program. The Gesture is destroyed before the
Widget. The Widget then gets dispose()d, which calls unparent()… boom.
I didn’t find an MCVE yet but would hope this logic is correct anyway:

The simplest fix is to make the loop in gtk_widget_reset_controllers()
skip GList nodes with a NULL Controller pointer, like most other such
loops, so we avoid passing the NULL to gtk_event_controller_reset().

In other, live cases, _gtk_widget_run_controllers() loops over the GList
and removes/frees nodes having NULL Controllers, so that should suffice.
But this clearly was not getting a chance to happen in the failing case.

https://bugzilla.gnome.org/show_bug.cgi?id=792624
gtk/gtkwidget.c